#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <sys/time.h>

#include "imbus_internal.h"
#include "im_component_info.h"

/************************** Declaration of internal functions ***************/
static void     __im_component_info_initialize  (IMPointer       info);
static void     __im_component_info_finalize    (IMPointer       info);
static void     __im_component_info_copy        (IMPointer       dest,
                                                 IMConstPointer  src);
static IMBool   __im_component_info_serialize   (IMConstPointer  obj,
                                                 IMPointer       stream);
static IMBool   __im_component_info_deserialize (IMPointer       obj,
                                                 IMPointer       stream);
static void     __im_component_info_class_init  (IMPointer       klass);

/****************** Declaration of object and class structure ************/
struct _IMComponentInfo
{
    IMObject object;

    /* private */
    IMUInt32         unique_id;
};

struct _IMComponentInfoClass
{
    IMObjectClass parent_class;

    IMQuark qsid;
    IMQuark qname;
    IMQuark qdesc;
    IMQuark qicon;
    IMQuark qroles;
};

/************************ Internal varable ************************/
static const IMObjectClass *__im_component_info_parent_class = 0;
static const IMComponentInfoClass *__im_component_info_class = 0;

/************* Implementation of internal functions ***************/

static void
__im_component_info_initialize (IMPointer info)
{
    ((IMComponentInfo*)info)->unique_id   = 0;
}

static void
__im_component_info_finalize (IMPointer info)
{
    IMComponentInfo *p = IM_COMPONENT_INFO (info);
    _im_assert (p != 0);
}

static void
__im_component_info_copy (IMPointer dest, IMConstPointer src)
{
    IMComponentInfo       *dp = IM_COMPONENT_INFO (dest);
    const IMComponentInfo *sp = IM_CONST_COMPONENT_INFO (src);

    _im_assert (dp && sp);

    dp->unique_id   = sp->unique_id;

    /* Call copy method of parent class */
    __im_component_info_parent_class->copy (dest, src);
}

static IMBool
__im_component_info_serialize (IMConstPointer obj, IMPointer stream)
{
    const IMComponentInfo *cp = IM_CONST_COMPONENT_INFO (obj);
    IMStream *sp = IM_STREAM (stream);

    _im_assert (cp && sp);

    /* Call parent serialize method */
    if (!__im_component_info_parent_class->serialize (obj, stream))
        return FALSE;

    if (!im_stream_put_uint32 (sp, cp->unique_id))
        return FALSE;
    return TRUE;
}

static IMBool
__im_component_info_deserialize (IMPointer obj, IMPointer stream)
{
    IMComponentInfo  *cp = IM_COMPONENT_INFO (obj);
    IMStream *sp = IM_STREAM (stream);
    IMType    type;

    _im_assert (cp && sp);

    /* Call parent deserialize method */
    if (!__im_component_info_parent_class->deserialize (obj, stream))
        return FALSE;

    type = im_stream_get_data_type (sp);
    if (type != IM_TYPE_UINT32 || !im_stream_get_uint32 (sp, &cp->unique_id))
        return FALSE;

    return TRUE;
}

static void
__im_component_info_class_init (IMPointer klass)
{
    IMObjectClass *cp = (IMObjectClass *)klass;
    IMComponentInfoClass *cicp = (IMComponentInfoClass *)klass;

    cp->copy        = __im_component_info_copy;
    cp->serialize   = __im_component_info_serialize;
    cp->deserialize = __im_component_info_deserialize;

    __im_component_info_parent_class = im_object_class_get_parent (cp);
    __im_component_info_class = cicp;

    cicp->qsid = im_quark_from_static_string (".s");
    cicp->qname = im_quark_from_static_string (".n");
    cicp->qdesc = im_quark_from_static_string (".d");
    cicp->qicon = im_quark_from_static_string (".i");
    cicp->qroles = im_quark_from_static_string (".r");
}

/************* Implementation of public functions ***************/
void
__im_type_register_component_info ()
{
    static IMTypeInfo im_component_info_type_info =
    {
        sizeof (IMComponentInfoClass),  /**< class_size >**/
        __im_component_info_class_init, /**< class_init >**/
        0,                              /**< class_finalize >**/

        sizeof (IMComponentInfo),       /**< instance_size >**/
        __im_component_info_initialize, /**< instance_init >**/
        __im_component_info_finalize,   /**< instance_finalize >**/
    };

    __im_type_register_builtin_class (IM_TYPE_OBJECT,
                                      IM_TYPE_COMPONENT_INFO,
                                      "ComponentInfo",
                                      &im_component_info_type_info,
                                      TRUE);
}

IMComponentInfo*
im_component_info_new ()
{
    IMComponentInfo *info =
        (IMComponentInfo *)im_object_new (IM_TYPE_COMPONENT_INFO);

    _im_assert (info);

    return info;
}

IMComponentInfo*
im_component_info_new_full (IMString *string_id, IMString *name,
                            IMString *desc, IMString *icon,
                            IMEventRoles *event_roles)
{
    IMComponentInfo *info;

    _im_return_val_if_fail (IM_IS_STRING(string_id) || !string_id, 0);
    _im_return_val_if_fail (IM_IS_STRING(name) || !name, 0);
    _im_return_val_if_fail (IM_IS_STRING(desc) || !desc, 0);
    _im_return_val_if_fail (IM_IS_STRING(icon) || !icon, 0);
    _im_return_val_if_fail (IM_IS_EVENT_ROLES(event_roles) || !event_roles, 0);

    info = (IMComponentInfo *)im_object_new (IM_TYPE_COMPONENT_INFO);
    _im_assert (info);

    if (string_id)
        im_object_set_quark_attachment (info, __im_component_info_class->qsid,
                                        string_id);
    if (name)
        im_object_set_quark_attachment (info, __im_component_info_class->qname,
                                        name);
    if (desc)
        im_object_set_quark_attachment (info, __im_component_info_class->qdesc,
                                        desc);
    if (icon)
        im_object_set_quark_attachment (info, __im_component_info_class->qicon,
                                        icon);
    if (event_roles)
        im_object_set_quark_attachment (info, __im_component_info_class->qroles,
                                        event_roles);
    return info;
}

void
im_component_info_set_unique_id (IMComponentInfo *info, IMUInt32 unique_id)
{
    _im_return_if_fail (IM_IS_COMPONENT_INFO(info));
    info->unique_id = unique_id;
}

IMUInt32
im_component_info_get_unique_id (IMComponentInfo *info)
{
    _im_return_val_if_fail (IM_IS_COMPONENT_INFO(info), 0);
    return info->unique_id;
}

void
im_component_info_set_string_id (IMComponentInfo *info, IMString *string_id)
{
    _im_return_if_fail (IM_IS_COMPONENT_INFO(info));
    _im_return_if_fail (IM_IS_STRING(string_id) || !string_id);

    if (string_id)
        im_object_set_quark_attachment (info, __im_component_info_class->qsid,
                                        string_id);
    else
        im_object_remove_quark_attachment (info, __im_component_info_class->qsid);
}

IMString*
im_component_info_get_string_id (IMComponentInfo *info)
{
    _im_return_val_if_fail (IM_IS_COMPONENT_INFO(info), 0);
    return IM_STRING(
        im_object_get_quark_attachment (info, __im_component_info_class->qsid));
}

void
im_component_info_set_name (IMComponentInfo *info, IMString *name,
                            const IMChar *lang)
{
    IMQuark qkey;
    _im_return_if_fail (IM_IS_COMPONENT_INFO(info));
    _im_return_if_fail (IM_IS_STRING(name) || !name);

    if (lang && *lang) {
        IMString *key = im_string_new_from_printf (".n.%s", lang);
        qkey = im_quark_from_string (im_string_c_str (key));
        im_object_unref (key);
    } else {
        qkey = __im_component_info_class->qname;
    }

    if (name)
        im_object_set_quark_attachment (info, qkey, name);
    else
        im_object_remove_quark_attachment (info, qkey);
}

IMString*
im_component_info_get_name (IMComponentInfo *info, const IMChar *lang)
{
    IMQuark qkey;
    _im_return_val_if_fail (IM_IS_COMPONENT_INFO(info), 0);

    if (lang && *lang) {
        IMString *key = im_string_new_from_printf (".n.%s", lang);
        qkey = im_quark_from_string (im_string_c_str (key));
        im_object_unref (key);
    } else {
        qkey = __im_component_info_class->qname;
    }

    return IM_STRING(im_object_get_quark_attachment (info, qkey));
}

void
im_component_info_set_description (IMComponentInfo *info, IMString *desc,
                                   const IMChar *lang)
{
    IMQuark qkey;
    _im_return_if_fail (IM_IS_COMPONENT_INFO(info));
    _im_return_if_fail (IM_IS_STRING(desc) || !desc);

    if (lang && *lang) {
        IMString *key = im_string_new_from_printf (".d.%s", lang);
        qkey = im_quark_from_string (im_string_c_str (key));
        im_object_unref (key);
    } else {
        qkey = __im_component_info_class->qdesc;
    }

    if (desc)
        im_object_set_quark_attachment (info, qkey, desc);
    else
        im_object_remove_quark_attachment (info, qkey);
}

IMString*
im_component_info_get_description (IMComponentInfo *info, const IMChar *lang)
{
    IMQuark qkey;
    _im_return_val_if_fail (IM_IS_COMPONENT_INFO(info), 0);

    if (lang && *lang) {
        IMString *key = im_string_new_from_printf (".d.%s", lang);
        qkey = im_quark_from_string (im_string_c_str (key));
        im_object_unref (key);
    } else {
        qkey = __im_component_info_class->qdesc;
    }

    return IM_STRING(im_object_get_quark_attachment (info, qkey));
}

void
im_component_info_set_icon (IMComponentInfo *info, IMString *icon)
{
    _im_return_if_fail (IM_IS_COMPONENT_INFO(info));
    _im_return_if_fail (IM_IS_STRING(icon) || !icon);

    if (icon)
        im_object_set_quark_attachment (info, __im_component_info_class->qicon,
                                        icon);
    else
        im_object_remove_quark_attachment (info, __im_component_info_class->qicon);
}

IMString*
im_component_info_get_icon (IMComponentInfo *info)
{
    _im_return_val_if_fail (IM_IS_COMPONENT_INFO(info), 0);
    return IM_STRING(
        im_object_get_quark_attachment (info, __im_component_info_class->qicon));
}

void
im_component_info_set_event_roles (IMComponentInfo *info,
                                   IMEventRoles *event_roles)
{
    _im_return_if_fail (IM_IS_COMPONENT_INFO(info));
    _im_return_if_fail (IM_IS_EVENT_ROLES(event_roles) || !event_roles);

    if (event_roles)
        im_object_set_quark_attachment (info, __im_component_info_class->qroles,
                                        event_roles);
    else
        im_object_remove_quark_attachment (info, __im_component_info_class->qroles);
}

IMEventRoles*
im_component_info_get_event_roles (IMComponentInfo *info)
{
    _im_return_val_if_fail (IM_IS_COMPONENT_INFO(info), 0);
    return IM_EVENT_ROLES(
        im_object_get_quark_attachment (info, __im_component_info_class->qroles));
}

void
im_component_info_set_languages (IMComponentInfo *info, IMString *langs)
{
    /* TODO */
}

IMString*
im_component_info_get_languages (IMComponentInfo *info)
{
    /* TODO */
    return 0;
}

/*
vi:ts=4:nowrap:ai:expandtab
*/
